//! \file arm_utils.c

#include <stdio.h>
#include <sys/user.h>
#include "check.h"
#include "arm_utils.h"
#include "memory_utils.h"

//------------------------------------------------------------------------------

#ifndef USE_PTRACE

//------------------------------------------------------------------------------

#define GET_REG(num) asm volatile("mov %[cur], r" #num "\n\t" :\
                                  [cur] "=r" (regs[num]));

TBGError GetRegisters(addr_t regs[ARM_REGISTER_COUNT]) {
    CHECK_DBG_ERR(regs, NULL_PTR); 
    GET_REG(0)  GET_REG(1)  GET_REG(2)  GET_REG(3) 
    GET_REG(4)  GET_REG(5)  GET_REG(6)  GET_REG(7) 
    GET_REG(8)  GET_REG(9)  GET_REG(10) GET_REG(11) 
    GET_REG(12) GET_REG(13) GET_REG(14) GET_REG(15) 
    return 0;
}

#undef GET_REG

//------------------------------------------------------------------------------

#else //#ifdef USE_PTRACE

//------------------------------------------------------------------------------

TBGError GetRegisters(addr_t regs[ARM_REGISTER_COUNT]) {
    TBGError ret = 0;
    CHECK_DBG_ERR(regs, NULL_PTR); 

    struct user_regs uregs = {};

    ptrace_session* pps = PtraceGetSetSession(NULL);
    CHECK_DBG_ERR(pps, CANNOT_GET_STORED_ARG);

    CHECK_CALL(PtraceGetRegs(pps, &uregs), exit_point, ret);
    CHECK_DBG_ERR(ARM_REGISTER_COUNT <= 18, TOO_MANY_REGISTERS);
    int i = 0;
    for(i = 0; i < ARM_REGISTER_COUNT; ++i)
        regs[i] = ((addr_t*)&uregs)[i];

exit_point:
    return ret;
}

//------------------------------------------------------------------------------

#endif //USE_PTRACE
